﻿using MvCamCtrl.NET;
using MvCameraControl;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Media3D;
using VM.PlatformSDKCS;

namespace CarPCBATest.Procedure
{
    internal class CameraGenTL
    {
        // ch:枚举的相机类型 | en:TLayerType for enumerate devices
        static readonly DeviceTLayerType enumTLayerType = DeviceTLayerType.MvGigEDevice | DeviceTLayerType.MvUsbDevice
    |   DeviceTLayerType.MvGenTLGigEDevice | DeviceTLayerType.MvGenTLCXPDevice | DeviceTLayerType.MvGenTLCameraLinkDevice | DeviceTLayerType.MvGenTLXoFDevice;

        public static List<IDeviceInfo> deviceInfoList = new List<IDeviceInfo>();
        public static IDeviceInfo deviceInfo { get; set; }

        public static IDevice device = null;
        public static bool isGrabbing = false;        // ch:是否正在取图 | en: Grabbing flag
        public static Thread receiveThread = null;    // ch:接收图像线程 | en: Receive image thread
        private static List<ImageBaseData> imageBaseDatas = new List<ImageBaseData>();
        private static bool getImage = false;
        //初始化相机
        public static void open()
        {
            BasicDemoWindow_Load();
        }
        private static void BasicDemoWindow_Load()
        {
            // ch: 初始化 SDK | en: Initialize SDK
            SDKSystem.Initialize();

            // ch: 枚举设备 | en: Enum Device List
            RefreshDeviceList();
        }
        private static void RefreshDeviceList()
        {
            //CloseMamera();
            // ch:创建设备列表 | en:Create Device List
            //cbDeviceList.Items.Clear();
            int nRet = DeviceEnumerator.EnumDevices(enumTLayerType, out deviceInfoList);
            if (nRet != MvError.MV_OK)
            {
                Console.WriteLine("Enumerate devices fail!", nRet);
                return;
            }
            deviceInfo = deviceInfoList[0];

        }
        //打开相机
        public static void OpenMamera()
        {
            if (deviceInfoList.Count == 0)
            {
                Console.Write("No device, please select", 0);
                return;
            }

            // ch:获取选择的设备信息 | en:Get selected device information
            IDeviceInfo deviceInfo = deviceInfoList[0];

            try
            {
                // ch:打开设备 | en:Open device
                device = DeviceFactory.CreateDevice(deviceInfo);
            }
            catch (Exception ex)
            {
                MessageBox.Show("Create Device fail!" + ex.Message);
                return;
            }

            int result = device.Open();
            if (result != MvError.MV_OK)
            {
                Console.Write("Open Device fail!", result);
                return;
            }

            //ch: 判断是否为gige设备 | en: Determine whether it is a GigE device
            if (device is IGigEDevice)
            {
                //ch: 转换为gigE设备 | en: Convert to Gige device
                IGigEDevice gigEDevice = device as IGigEDevice;

                // ch:探测网络最佳包大小(只对GigE相机有效) | en:Detection network optimal package size(It only works for the GigE camera)
                int optionPacketSize;
                result = gigEDevice.GetOptimalPacketSize(out optionPacketSize);
                if (result != MvError.MV_OK)
                {
                    Console.Write("Warning: Get Packet Size failed!", result);
                }
                else
                {
                    result = device.Parameters.SetIntValue("GevSCPSPacketSize", (long)optionPacketSize);
                    if (result != MvError.MV_OK)
                    {
                        Console.Write("Warning: Set Packet Size failed!", result);
                    }
                }
            }

            // ch:设置采集连续模式 | en:Set Continues Aquisition Mode
            device.Parameters.SetEnumValueByString("AcquisitionMode", "Continuous");
            device.Parameters.SetEnumValueByString("TriggerMode", "Off");

            // ch:打开触发模式 | en:Open Trigger Mode
            //device.Parameters.SetEnumValueByString("TriggerMode", "On");

            // ch:触发源选择:0 - Line0; | en:Trigger source select:0 - Line0;
            //           1 - Line1;
            //           2 - Line2;
            //           3 - Line3;
            //           4 - Counter;
            //           7 - Software;
            // device.Parameters.SetEnumValueByString("TriggerSource", "Software");

            // ch:获取参数 | en:Get parameters
            // bnGetParam_Click(null, null);
            //ch: 设置合适的缓存节点数量 | en: Setting the appropriate number of image nodes
            //device.StreamGrabber.SetImageNodeNum(5);

            //// ch:注册回调函数 | en:Register image callback
            //device.StreamGrabber.FrameGrabedEvent += FrameGrabedEventHandler;
            //Console.Write("开启抓图");
            //// ch:开启抓图 || en: start grab image
            //result = device.StreamGrabber.StartGrabbing();
            //if (result != MvError.MV_OK)
            //{
            //    Console.WriteLine("Start grabbing failed:{0:x8}", result);
            //    return;
            //}

            //// ch:停止抓图 | en:Stop grabbing
            //result = device.StreamGrabber.StopGrabbing();
            //if (result != MvError.MV_OK)
            //{
            //    Console.WriteLine("Stop grabbing failed:{0:x8}", result);
            //    return;
            //}

            //// ch:关闭设备 | en:Close device
            //result = device.Close();
            //if (result != MvError.MV_OK)
            //{
            //    Console.WriteLine("Close device failed:{0:x8}", result);
            //    return;
            //}

            //// ch:销毁设备 | en:Destroy device
            //device.Dispose();
            //device = null;
        }
        static void FrameGrabedEventHandler(object sender, FrameGrabbedEventArgs e)
        {
            Console.WriteLine("Get one frame: Width[{0}] , Height[{1}] , ImageSize[{2}], FrameNum[{3}]", e.FrameOut.Image.Width, e.FrameOut.Image.Height, e.FrameOut.Image.ImageSize, e.FrameOut.FrameNum);
            //imageBaseDatas.Add(CCDToImageBaseData(pData, e.FrameOut.Image));
            //getImage = true;
        }
        //开始采集
        public static void StartGrab()
        {
            try
            {
                // ch:标志位置位true | en:Set position bit true
                isGrabbing = true;
                //pictureBoxHandle = displayArea.Handle;

                receiveThread = new Thread(ReceiveThreadProcess);
                receiveThread.Start();
            }
            catch (Exception ex)
            {
                MessageBox.Show("Start thread failed!, " + ex.Message);
                return;
            }

            // ch:开始采集 | en:Start Grabbing
            int result = device.StreamGrabber.StartGrabbing();
            if (result != MvError.MV_OK)
            {
                isGrabbing = false;
                receiveThread.Join();
                Console.Write("Start Grabbing Fail!", result);
                return;
            }
        }
        public static void ReceiveThreadProcess()
        {
            IFrameOut frameOut = null;
            int result = MvError.MV_OK;

            while (isGrabbing)
            {
                result = device.StreamGrabber.GetImageBuffer(1000, out frameOut);
                if (result == MvError.MV_OK)
                {
                    Console.WriteLine("Get one frame: Width[{0}] , Height[{1}] , ImageSize[{2}], FrameNum[{3}]", frameOut.Image.Width, frameOut.Image.Height, frameOut.Image.ImageSize, frameOut.FrameNum);
                    imageBaseDatas.Add(CCDToImageBaseData(frameOut));
                    isGrabbing = false ;
                    CloseMamera();
                    getImage = true;
                }
            }
        }
        public static ImageBaseData GetCurrentImage()
        {
            imageBaseDatas.Clear();
            getImage = false;
            StartGrab();
            bool timeOut = false;
            //Task.Run(() =>
            //{
            //    Thread.Sleep(2000);
            //    timeOut = true;
            //});
            while (!getImage)
            {
                if (imageBaseDatas.Count>0)
                    break;
            }

            CloseMamera();
            //if (timeOut)
            //{
            //    throw new Exception("采图执行异常0");
            //}
            //if (imageBaseDatas.Count < 1)
            //{
            //    throw new Exception("采图执行异常1");
            //}
            return imageBaseDatas[0];
        }

        public static void CloseMamera()
        {
            // ch:取流标志位清零 | en:Reset flow flag bit
            if (isGrabbing == true)
            {
                // ch:标志位设为false | en:Set flag bit false
                isGrabbing = false;
                receiveThread.Join();

                // ch:停止采集 | en:Stop Grabbing
                int result = device.StreamGrabber.StopGrabbing();
                if (result != MvError.MV_OK)
                {
                    Console.Write("Stop Grabbing Fail!", result);
                }
            }

            // ch:关闭设备 | en:Close Device
            if (device != null)
            {
                device.Close();
                device.Dispose();
            }
        }
        private static ImageBaseData CCDToImageBaseData(IFrameOut frame)
        {
            ImageBaseData imageBaseData = new ImageBaseData();
            imageBaseData.Width = (int)frame.Image.Width;
            imageBaseData.Height = (int)frame.Image.Height;
            imageBaseData.DataLen = (uint)frame.FrameLen;

            if (frame.Image.PixelType == MvGvspPixelType.PixelType_Gvsp_Mono8)
            {
                imageBaseData.Pixelformat = (int)VMPixelFormat.VM_PIXEL_MONO_08;
            }
            else if (frame.Image.PixelType == MvGvspPixelType.PixelType_Gvsp_RGB8_Packed)
            {
                imageBaseData.Pixelformat = (int)VMPixelFormat.VM_PIXEL_RGB24_C3;
            }
            else
            {
                imageBaseData.Pixelformat = (int)VMPixelFormat.VM_PIXEL_RGB24_C3;
            }
            imageBaseData.ImageData = new byte[frame.FrameLen];
            //Marshal.Copy(pdata, imageBaseData.ImageData, 0, (int)frame.FrameLen);
            return imageBaseData;
        }
    }
}
